package com.taoism.utils;

import com.taoism.annotation.Where;
import com.taoism.customEnum.SQLMethodEnum;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Hana数据库语句生成工具
 *
 * @author 李嘉
 * @version 1.0
 * @Description Hana数据库语句生成工具
 * @date 2019-07-27 16:11
 */
public class HanaSQLGenerateUtil {

    private final static String IGNORE_FIELD = "serialVersionUID";

    /**
     * 生成单条SQL语句
     *
     * @param object
     * @return
     */
    public static String generateSQL(Object object, SQLMethodEnum sqlMethodEnum) {
        if (object instanceof ArrayList) {
            return generateSQL((ArrayList) object, sqlMethodEnum);
        } else {
            List<Object> list = new ArrayList<>();
            list.add(object);
            return generateSQL(list, sqlMethodEnum);
        }
    }

    /**
     * 生成多条SQL语句
     *
     * @param list
     * @return
     */
    public static String generateSQL(List<Object> list, SQLMethodEnum sqlMethodEnum) {
        if (list == null || list.size() <= 0) {
            return "";
        }
        Object object = list.get(0);
        Class<?> clasz = object.getClass();

        String tableName = clasz.getDeclaredAnnotation(Table.class).name();
        if (StringUtil.isEmpty(tableName)) {
            return "";
        }

        Field[] fields = clasz.getDeclaredFields();

        StringBuffer stringSQL = new StringBuffer();

        try {
            if (sqlMethodEnum == SQLMethodEnum.INSERT) {
                generateInsertSQL(fields, list, stringSQL, tableName);
            } else if (sqlMethodEnum == SQLMethodEnum.UPDATE) {
                generateUpdateSQL(fields, list, stringSQL, tableName);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return stringSQL.toString();
    }

    /**
     * 生成插入语句
     *
     * @param fields
     * @param list
     * @param stringSQL
     * @param tableName
     */
    private static void generateInsertSQL(Field[] fields, List<Object> list, StringBuffer stringSQL, String tableName) {
        try {
            Integer index = 1;
            for (Integer i = 0; i < list.size(); i++) {
                stringSQL.append("INSERT INTO ");
                stringSQL.append(tableName);
                stringSQL.append("(");
                generateFieldSQL(fields, stringSQL);
                stringSQL.append(") VALUES");
                Object object = list.get(i);
                if (object.getClass().getDeclaredField(IGNORE_FIELD) != null) {
                    index = 2;
                } else {
                    index = 1;
                }
                stringSQL.append("(");
                generateValueSQL(fields, object, stringSQL, index);
                stringSQL.append(")");
                if ((i + 1) < list.size()) {
                    stringSQL.append(";\r\n");
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 生成更新SQL
     *
     * @param fields
     * @param list
     * @param stringSQL
     * @param tableName
     * @throws Exception
     */
    private static void generateUpdateSQL(Field[] fields, List<Object> list, StringBuffer stringSQL, String tableName) throws Exception {
        Integer index = 0;
        boolean isFirst = true;
        StringBuffer stringWhere = new StringBuffer();
        for (Integer i = 0; i < list.size(); i++) {
            Object object = list.get(i);
            isFirst = true;
            if (object.getClass().getDeclaredField(IGNORE_FIELD) != null) {
                index = 2;
            } else {
                index = 1;
            }
            stringSQL.append("UPDATE ");
            stringSQL.append(tableName);
            stringSQL.append(" SET ");
            for (Field field : fields) {
                field.setAccessible(true);
                Column column = field.getDeclaredAnnotation(Column.class);
                String columnName = "";
                if (column != null) {
                    columnName = column.name();
                } else {
                    columnName = field.getName();
                }
                if (!columnName.equalsIgnoreCase(IGNORE_FIELD)) {
                    Object objValue = field.get(object);
                    if (!StringUtil.isEmpty(objValue)) {
                        Id idInfo = field.getDeclaredAnnotation(Id.class);
                        Where where = field.getDeclaredAnnotation(Where.class);
                        if (idInfo == null) {
                            if (!isFirst && !StringUtil.isEmpty(objValue)) {
                                stringSQL.append(",");
                            } else {
                                isFirst = false;
                            }
                            stringSQL.append(columnName);
                            stringSQL.append(" = '");
                            stringSQL.append(objValue);
                            stringSQL.append("'");
                        }
                        if (index == 2 || index == 1) {
                            stringWhere.append(" WHERE 1 = 1 ");
                        }
                        if (where != null) {
                            stringWhere.append(" AND ");
                            stringWhere.append(columnName);
                            stringWhere.append(" = '");
                            stringWhere.append(objValue);
                            stringWhere.append("' ");
                        }
                    }
                }
                index++;
            }
            if (!StringUtil.isEmpty(stringWhere.toString())) {
                stringSQL.append(stringWhere);
            }
            if (i < list.size()) {
                stringSQL.append(";\r\n");
            }
            stringWhere = new StringBuffer();
        }
    }

    /**
     * 生成字段段SQL
     *
     * @param fields
     * @param stringSQL
     * @throws Exception
     */
    private static void generateFieldSQL(Field[] fields, StringBuffer stringSQL) {
        Integer index = 1;
        for (Integer i = 0; i < fields.length; i++) {
            if (fields[i].getName().equalsIgnoreCase(IGNORE_FIELD)) {
                index = 2;
            }
        }
        for (Field field : fields) {
            Column column = field.getDeclaredAnnotation(Column.class);
            String columnName = "";
            if (column != null) {
                columnName = column.name();
            } else {
                columnName = field.getName();
            }
            if (!columnName.equalsIgnoreCase(IGNORE_FIELD)) {
                stringSQL.append("\"");
                stringSQL.append(columnName);
                stringSQL.append("\"");
                if (index < fields.length) {
                    stringSQL.append(",");
                }
                index++;
            }
        }
    }

    /**
     * 生成值段SQL
     *
     * @param fields
     * @param object
     * @param stringSQL
     * @throws Exception
     */
    private static void generateValueSQL(Field[] fields, Object object, StringBuffer stringSQL, Integer index) throws Exception {
        for (Field field : fields) {
            if (!field.getName().equalsIgnoreCase(IGNORE_FIELD)) {
                field.setAccessible(true);
                Object objValue = field.get(object);
                if (!StringUtil.isEmpty(objValue)) {
                    stringSQL.append("'");
                    stringSQL.append(objValue);
                    stringSQL.append("'");
                } else {
                    stringSQL.append("NULL");
                }
                if (index < fields.length) {
                    stringSQL.append(",");
                }
                field.setAccessible(false);
            }
            index++;
        }
    }
}
